﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DTS
{
    class Controller
    {
        AlgorithmController algorithmController;
        HistoriaSpolkiController historiaSpolkiController;
        PortfelController portfelController;
        SpolkaController spolkaController;
        TransakcjaController transakcjaController;
        DbAdapter dbAdapter;
        Dictionary<String, Notowania> notowania;
        Double procentPortfela = 0.2;
        public Controller()
        {
            algorithmController = new AlgorithmController();
            historiaSpolkiController = new HistoriaSpolkiController();
            portfelController = new PortfelController();
            spolkaController = new SpolkaController();
            transakcjaController = new TransakcjaController();
            dbAdapter = new DbAdapter();
            PobierzPortfelZBazy();
            PobierzSpolkiZBazy();
            pobierzTransakcjeZBazy();
        }
        public void setProwizja(Double val)
        {
            portfelController.setProwizja(val);
        }
        public HistoriaSpolki getHistoriaSpolki(String symbol)
        {
            symbol = symbol.ToLower();
            PobierzHistorieZBazy(symbol);
            return historiaSpolkiController.getHistoriaSpolki(symbol);
        } // OK - ale nie pobiera zaktualizowanych
        public HistoriaSpolki getHistoriaSpolki(String symbol, DateTime DataBegin, DateTime dataEnd)
        {
            symbol = symbol.ToLower();
            PobierzHistorieZBazy(symbol);
            return historiaSpolkiController.getHistoriaSpolki(symbol,DataBegin,dataEnd);
        } // OK
        public List<Spolka> getAllSpolki()
        {
            return spolkaController.getAllSpolki();
        } // OK
        public Spolka getSpolka(String symbol)
        {
            symbol = symbol.ToLower();
            return spolkaController.getSpolka(symbol);     
        } // OK
        public List<Spolka> getSpolkaSektor(String sektor)
        {
            return spolkaController.getSpolkaSektor(sektor);
        } //OK
        public List<Spolka> getSpolkaKapitalizacja(Double min,Double max)
        {
            return spolkaController.getSpolkaKapitalizacja(min, max);
        } // OK
        public List<Spolka> findSpolka(String ciag)
        {
            return spolkaController.findSpolka(ciag);
        } //OK
        public bool transakcja(String symbol, int ilosc, bool isShort, DateTime data, String kto)
        {
            if (ilosc <= 0) return false;
            Double cena = notowania[symbol].GetClose();
            if (getSpolka(symbol) == null) return false;
            Walor wToDB = new Walor("-1", true, -1, -1.0, kto);
            List<Transakcja> toRet = portfelController.transakcja(symbol, ilosc, isShort, cena,ref wToDB,data,kto);
            if (toRet == null) return false;
            transakcjaController.addTransakcja(toRet);
            dbAdapter.InsertTransakcja(toRet, wToDB);
            dbAdapter.UpdateGotowka(portfelController.getGotowka());
            return true;
        }
        public bool transakcjaSymulacja(String symbol, int ilosc, bool isShort,Double cena, DateTime data,String kto)
        {
            if (ilosc <= 0) return false;
            if (getSpolka(symbol) == null) return false;
            Walor wToDB = new Walor("-1", true, -1, -1.0, kto);
            List<Transakcja> toRet = portfelController.transakcja(symbol, ilosc, isShort, cena, ref wToDB, data,kto);
            if (toRet == null) return false;
            transakcjaController.addTransakcja(toRet);
            dbAdapter.InsertTransakcja(toRet, wToDB);
            dbAdapter.UpdateGotowka(portfelController.getGotowka());
            return true;
        }
        public Double getGotowka()
        {
            return portfelController.getGotowka();
        } // OK
        public List<Walor> getWalory()
        {
            return portfelController.getWalory();
        }  // OK
        public Walor getWalor(String symbol)
        {
            return portfelController.getWalor(symbol);
        }
        public void setProcentPortfela(Double val)
        {
            procentPortfela = val;
        }
        public void setProgEMA(Double val)
        {
            algorithmController.setProgEMA(val);
        }
        public void setProgSMA(Double val)
        {
            algorithmController.setProgSMA(val);
        }
        public bool subGotowka(Double ile)
        {
            bool wynik = portfelController.subGotowka(ile);
            if (wynik) 
            { 
                dbAdapter.UpdateGotowka(portfelController.getGotowka());
                Transakcja t = new Transakcja("$$$", 0, 1, ile, 0, 0, DateTime.Now,"USER");
                transakcjaController.addTransakcja(t);
                dbAdapter.InsertTransakcja(t);
            }
            return wynik;
        } // OK
        public void addGotowka(Double ile)
        {
            portfelController.addGotowka(ile);
            Transakcja t = new Transakcja("$$$", 0, 2, ile, 0, 0, DateTime.Now, "USER");
            transakcjaController.addTransakcja(t);
            dbAdapter.InsertTransakcja(t);
            dbAdapter.UpdateGotowka(portfelController.getGotowka());
        } // OK
        public List<Transakcja> getTransaction()
        {
            return transakcjaController.getTransactions();
        } // OK
        public List<Transakcja> getTransaction(String symbol)
        {
            return transakcjaController.getTransactions(symbol);
        } // OK
        public List<Transakcja> getTransaction(DateTime dataStart, DateTime dataStop)
        {
            return transakcjaController.getTransactions(dataStart, dataStop);
        } // OK
        public List<Transakcja> getTransaction(String symbol,DateTime dataStart, DateTime dataStop)
        {
            return transakcjaController.getTransactions(symbol,dataStart, dataStop);
        } // OK
        public Dictionary<String, Notowania> getNotowania()
        {
            if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
            {
                Console.WriteLine("weekend");
                notowania = dbAdapter.PobierzAktualneNotowaniaWeekend();
                if (notowania.Count == 0)
                    notowania = dbAdapter.PobierzAktualneNotowania();
            }
            else
            {
                Console.WriteLine("normal");
                notowania = dbAdapter.PobierzAktualneNotowania();
                Console.WriteLine(notowania.Count);
                if (notowania.Count == 0)
                    notowania = dbAdapter.PobierzAktualneNotowaniaWeekend();
            }     
            return notowania;
        }
        public List<String> getObserwowane()
        {
            return dbAdapter.SelectObserwowaneSpolki();
        }
        public void addObserwowana(String symbol)
        {
            dbAdapter.InsertObserwowanaSpolka(symbol);
        }
        public void deleteObserowowana(String symbol)
        {
            dbAdapter.DeleteObserwowanaSpolka(symbol);
        }
        private void PobierzSpolkiZBazy()
        {
            if (spolkaController.getCount() < 100) spolkaController.AddAllSpolka(dbAdapter.SelectSpolki());
        }
        private void pobierzTransakcjeZBazy()
        {
            if (transakcjaController.getCount() < 1)
                transakcjaController.addTransakcja(dbAdapter.SelectTransakcje());
        }
        private void PobierzPortfelZBazy()
        {
            portfelController.setWalory(dbAdapter.SelectWalory());
            portfelController.setGotowka(dbAdapter.SelectGotowka());
        }
        private void PobierzHistorieZBazy(String symbol)
        {
            if (historiaSpolkiController.getHistoriaSpolki(symbol) != null) return;
            List<Swieczka> toInsert = dbAdapter.SelectDaneHistoryczne(symbol);
            historiaSpolkiController.addHistoriaSpolki(symbol, toInsert);
        }
        public int getDecision(String algName, HistoriaSpolki hs, DateTime actualDay)
        {
            return algorithmController.getDecision(algName, hs, actualDay);
        }
        public int getDecision(String algName, HistoriaSpolki hs, Double cena, DateTime actualDay)
        {
            return algorithmController.getDecision(algName, hs, cena, actualDay);
        }
        public int getDecisionAll(HistoriaSpolki hs, Double cena, DateTime actualDay)
        {
            return algorithmController.getDecisionAll(hs, cena, actualDay);
        }
        public int getDecisionAll(HistoriaSpolki hs, DateTime actualDay)
        {
            return algorithmController.getDecisionAll(hs, actualDay);
        }
        public void computeChange(String symbol, DateTime data)
        {
            if (!this.getHistoriaSpolki(symbol).czyDzienSesja(data)) return;
            Double cena = this.getHistoriaSpolki(symbol).getSwieczka(data).GetClose();
            Double iloscD = portfelController.getGotowka()* procentPortfela / cena;
            int ilosc = (int) iloscD;
            Walor w = portfelController.getWalor(symbol);
            int decyzjaOgolu = this.getDecisionAll(this.getHistoriaSpolki(symbol), data);
            if (decyzjaOgolu == 0 || decyzjaOgolu == -1 || decyzjaOgolu == 1) return;
            if (decyzjaOgolu == -2)
            {
                if (w != null)
                {
                    if (!w.getIsShort())
                        transakcjaSymulacja(w.getSymbol(), w.getLiczba(),true,cena, data,"MIX");
                }
            }
            if (decyzjaOgolu <= -3)
            {
                if (w == null)
                {
                    transakcjaSymulacja(symbol, ilosc, true, cena, data, "MIX");
                }
                else
                {
                    if (!w.getIsShort())
                    {
                        transakcjaSymulacja(symbol, 2 * w.getLiczba(), true, cena, data, "MIX");
                    }
                }
            }
            if (decyzjaOgolu == 2)
            {
                if (w != null)
                {
                if (w.getIsShort())
                    transakcjaSymulacja(w.getSymbol(), w.getLiczba(), false, cena, data, "MIX");
                }
            }
            if (decyzjaOgolu >= 3)
            {
                if (w == null)
                {
                    transakcjaSymulacja(symbol, ilosc, false, cena, data, "MIX");
                }
                else
                {
                    if (w.getIsShort())
                    {
                        transakcjaSymulacja(symbol, 2 * w.getLiczba(), false, cena, data, "MIX");
                    }
                }
            }
        }
        public void computeChangeAlgorithm(String algorithm, String symbol, DateTime data)
        {
            if (!this.getHistoriaSpolki(symbol).czyDzienSesja(data)) return;
            Double cena = this.getHistoriaSpolki(symbol).getSwieczka(data).GetClose();
            Double iloscD = portfelController.getGotowka() * procentPortfela / cena;
            int ilosc = (int)iloscD;
            Console.WriteLine(ilosc);
            Walor w = portfelController.getWalor(symbol);
            int decyzja = this.getDecision(algorithm,this.getHistoriaSpolki(symbol), data);
            if (decyzja == -1)
            {
                if (w == null)
                {
                    transakcjaSymulacja(symbol, ilosc, true, cena, data,algorithm);
                }
                else
                {
                    if (!w.getIsShort())
                    {
                        transakcjaSymulacja(symbol, 2 * w.getLiczba(), true, cena, data, algorithm);
                    }
                }
            }
            if (decyzja == 1)
            {
                if (w == null)
                {
                    transakcjaSymulacja(symbol, ilosc, false, cena, data, algorithm);
                }
                else
                {
                    if (w.getIsShort())
                    {
                        transakcjaSymulacja(symbol, 2 * w.getLiczba(), false, cena, data, algorithm);
                    }
                }
            }
        }
        public void clearUD()
        {
            dbAdapter.ClearUserData();
            algorithmController = new AlgorithmController();
            historiaSpolkiController = new HistoriaSpolkiController();
            portfelController = new PortfelController();
            spolkaController = new SpolkaController();
            transakcjaController = new TransakcjaController();
            dbAdapter = new DbAdapter();
            PobierzPortfelZBazy();
            PobierzSpolkiZBazy();
            pobierzTransakcjeZBazy();
        }
    }
}
